﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;

namespace TSON.GeoCOM
{
    public class TsSerialPort : SerialPort
    {
        /// <summary>
        /// 为了控制对串口的读写，设置此变量
        /// 为FALSE时，只能写不能读
        /// 为TRUE时，只能读不能写
        /// </summary>
        private bool readWriteFlag = false;
        private bool isReading = false;
        private int expireTime = 20000;
        private string receivedString = string.Empty;
        public int ExpireTime
        {
            get
            {
                return this.expireTime;
            }
            set
            {
                this.expireTime = value;
            }
        }
        public TsSerialPort()
            : base()
        {
            this.Parity = Parity.None;
            this.DataBits = 8;
            this.StopBits = StopBits.One;
            this.DataReceived += TsSerialPort_DataReceived;
        }
        public TsSerialPort(string portName, int baudRate)
            : base(portName, baudRate)
        {
            this.Parity = Parity.None;
            this.DataBits = 8;
            this.StopBits = StopBits.One;
            this.DataReceived += TsSerialPort_DataReceived;
        }

        void TsSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //所有的接收字符串都以CR/LF结尾
            if (this.readWriteFlag == false)
            {
                this.isReading = false;
                return;
            }
            if (this.isReading == false)
            {
                this.isReading = true;
                this.receivedString = this.ReadExisting();
            }
            else
            {
                this.receivedString += this.ReadExisting();
            }

            if (this.receivedString.EndsWith("\r\n"))
            {
                this.isReading = false;
                this.readWriteFlag = false;
            } 
        }

        public string getResponse(string requestString)
        {
            int i = 0;
            if (this.IsOpen)
            {
                while (this.expireTime > 500 * i)
                {
                    if (this.readWriteFlag == false)
                    {
                        this.readWriteFlag = true;
                        this.Write(requestString);
                        break;
                    }
                    else
                    {
                        i++;
                        System.Threading.Thread.Sleep(500);
                        continue;
                    }
                }
            }
            if (this.expireTime <= 500 * i)
            {
                throw new Exception("写数据超时！");
            }
            i = 0;
            while (this.expireTime > 500 * i)
            {
                if (this.readWriteFlag == true)
                {
                    i++;
                    System.Threading.Thread.Sleep(500);
                    continue;
                }
                else
                    break;
            }
            if (this.expireTime <= 500 * i)
            {
                throw new Exception("读数据超时！");
            }
            return this.receivedString;
        }
        public void ClearBuffer()
        {
            this.DiscardInBuffer();
            this.DiscardOutBuffer();
        }        
    
    }
    public class Helpers
    {
        public static RC getRcCode(string responseString)
        {
            string infoString = responseString.Split(':')[1];
            infoString = infoString.Trim();
            int rcNum = Convert.ToInt32(infoString.Split(',')[0]);
            return (RC)rcNum;
        }
        public static string getInfoString(string responseString)
        {
            string infoString = responseString.Split(':')[1];
            infoString = infoString.Trim();
            infoString = infoString.Split(new char[] { ',' }, 2)[1];
            return infoString;
        }
        
    }
    public enum RC
    {
        GRC_OK = 0,                         //Execution successful.

        GRC_IVPARAM = 2,//One or both tolerance values not within the boundaries
        //(1.57079E-06[rad] =1[cc]
        //to 1.57079E-04[rad] =100[cc]).

        GRC_IVRESULT = 3, //Wrong values entered.

        GRC_FATAL = 4, //Fatal error.

        GRC_NOT_IMPL = 5, //No motorization available (no automated instrument).

        GRC_SETINCOMPLETE = 7, //Invalid number of parameters.

        GRC_ABORT = 8,//Measurement through customer aborted.

        GRC_SHUT_DOWN = 12, //System power off through customer.

        GRC_NA = 27,// GeoCOM Robotic license key not available.

        GRC_ATA_NO_TARGET = 517, //No target detected, no previous Fine Adjust

        GRC_ATA_STRANGE_LIGHT = 524, //Not the spot of the own target illuminator.

        GRC_TMC_NO_FULL_CORRECTION = 1283,   //The results are not corrected by all active sensors. Coordinates are 
        //available. In order to secure which correction is missing use the
        //both functions TMC_IfDataAzeCorrError and TMC_IfDataIncCorrError

        GRC_TMC_ACCURACY_GUARANTEE = 1284,  // Accuracy is not guaranteed, because the result is containing
        //measurement data which accuracy could not be verified by
        //the system. Co-ordinates are available.

        GRC_TMC_ANGLE_OK = 1285,// Angle values okay, but no valid distance. Co-ordinates are
        //not available.

        GRC_TMC_ANGLE_NO_FULL_CORRECTION = 1288,// No distance data available but angle data are valid. The return
        //code is equivalent to the GRC_TMC_NO_FULL_CORRECTION
        //and relates to the angle data. Co-ordinates are not available.
        //Perform a distance measurement first before you call this
        //function.

        GRC_TMC_ANGLE_NO_ACC_GUARANTY = 1289,// Only the angle measurement is valid but its accuracy cannot
        //be guaranteed (the tilt measurement is not available).

        GRC_TMC_ANGLE_ERROR = 1290,// Angle or inclination measurement error. Check inclination
        //modes in commands.

        GRC_TMC_DIST_PPM = 1291,// No distance measurement respectively no distance data
        //because of wrong EDM settings. Co-ordinates are not
        //available.

        GRC_TMC_DIST_ERROR = 1292, //No measuring, because of missing target point, co-ordinates
        //are not available.
        //Aim target point and try it again

        GRC_TMC_BUSY = 1293,//TMC resource is locked respectively TMC task is busy.
        //Repeat measurement.

        TMC_SIGNAL_ERROR = 1294, //Error, no signal on EDM (only in signal mode)

        GRC_MOT_UNREADY = 1792, //Instrument has no motorization

        GRC_MOT_BUSY = 1793, //Subsystem is busy (e.g. controller already started).

        GRC_MOT_NOT_OCONST = 1794, //Drive is not in mode MOT_OCONST (set by MOT_StartController).

        GRC_MOT_NOT_CONFIG= 1795, //System is not in state MOT_CONFIG or MOT_BUSY_OPEN_END(e.g. missing ‘start controller’).       

        GRC_COM_TIMEDOUT = 3077, //Communication timeout. (perhaps increase COM timeout, see COM_SetTimeout)

        GRC_AUT_TIMEOUT = 8704, //Time out while positioning of one or both axes. (perhaps increase AUT time out, see AUT_SetTimeout)

        GRC_AUT_ANGLE_ERROR = 8706, //Angle measurement error
        
        GRC_AUT_MOTOR_ERROR = 8707, //Instrument has no ‘motorization’.

        GRC_AUT_INCACC = 8708, //Position not exactly reached

        GRC_AUT_DEV_ERROR = 8709, //During the determination of the angle deviation error detected, repeat positioning

        GRC_AUT_NO_TARGET = 8710, //No target found

        GRC_AUT_MULTIPLE_TARGETS = 8711, //Multiple targets found.

        GRC_AUT_BAD_ENVIRONMENT = 8712, //Inadequate environment conditions.

        GRC_AUT_DETECTOR_ERROR = 8713, //Error in target acquisition.

        GRC_AUT_NOT_ENABLED = 8714, //ATR mode not enabled, enable ATR mode

        GRC_AUT_CALACC = 8715,  //ATR-calibration failed

        GRC_AUT_ACCURACY = 8716, //Inexact fine position, repeat positioning

        GRC_AUT_NO_WORKING_AREA = 8720, //Working area not defined

        GRC_AUT_SIDECOVER_ERR = 8723, //Sidecover open

    };

    public enum ON_OFF_TYPE // on/off switch type
    {
        OFF = 0, // Switch is off
        ON = 1 // Switch is on
    };
}
